﻿#ifndef __INC_QG_OPENGL_V4_H__
#define __INC_QG_OPENGL_V4_H__

#ifdef _MSC_VER
#pragma once
#endif

#if _SB_WINDOWS_
#	include <GL/gl.h>
#	include "glext/glext.h"
#	include "glext/wglext.h"
#	ifdef _MSC_VER
#		pragma comment(lib, "opengl32")
#	endif
#elif _SB_APPLE_
#	include <OpenGL/gl.h>
#	include "glext/glext.h"
#else
#	include <GL/gl.h>
#	include <GL/glx.h>
#	include <GL/glext.h>
#	include <GL/glxext.h>
#endif

//
#define GL_LUMINANCE16F					GL_LUMINANCE16F_ARB
#define GL_LUMINANCE32F					GL_LUMINANCE32F_ARB

//
#if _SB_WINDOWS_
#define QGGL_ENTRYPOINT_LIST(decl) \
	decl(PFNGLCLEARDEPTHFPROC, glClearDepthf) \
	decl(PFNGLDEPTHRANGEFPROC, glDepthRangef) \
	decl(PFNGLACTIVETEXTUREPROC, glActiveTexture) \
	decl(PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedTexSubImage2D) \
	decl(PFNGLGENERATEMIPMAPPROC, glGenerateMipmap) \
	decl(PFNGLBLENDEQUATIONPROC, glBlendEquation) \
	decl(PFNGLBLENDEQUATIONIPROC, glBlendEquationi) \
	decl(PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate) \
	decl(PFNGLBLENDEQUATIONSEPARATEIPROC, glBlendEquationSeparatei) \
	decl(PFNGLBLENDFUNCIPROC, glBlendFunci) \
	decl(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate) \
	decl(PFNGLBLENDFUNCSEPARATEIPROC, glBlendFuncSeparatei) \
	decl(PFNGLCOLORMASKIPROC, glColorMaski) \
	decl(PFNGLENABLEIPROC, glEnablei) \
	decl(PFNGLDISABLEIPROC, glDisablei) \
	decl(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) \
	decl(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) \
	decl(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) \
	decl(PFNGLVERTEXATTRIB4FVPROC, glVertexAttrib4fv) \
	decl(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) \
	decl(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) \
	decl(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers) \
	decl(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) \
	decl(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D) \
	decl(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers) \
	decl(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer) \
	decl(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) \
	decl(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) \
	decl(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer) \
	decl(PFNGLGETRENDERBUFFERPARAMETERIVPROC, glGetRenderbufferParameteriv) \
	decl(PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC, glGetFramebufferAttachmentParameteriv) \
	decl(PFNGLCREATEPROGRAMPROC, glCreateProgram) \
	decl(PFNGLDELETEPROGRAMPROC, glDeleteProgram) \
	decl(PFNGLATTACHSHADERPROC, glAttachShader) \
	decl(PFNGLDETACHSHADERPROC, glDetachShader) \
	decl(PFNGLGETATTACHEDSHADERSPROC, glGetAttachedShaders) \
	decl(PFNGLGETPROGRAMIVPROC, glGetProgramiv) \
	decl(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) \
	decl(PFNGLGETACTIVEATTRIBPROC, glGetActiveAttrib) \
	decl(PFNGLGETACTIVEUNIFORMPROC, glGetActiveUniform) \
	decl(PFNGLGETATTRIBLOCATIONPROC, glGetAttribLocation) \
	decl(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) \
	decl(PFNGLCREATESHADERPROC, glCreateShader) \
	decl(PFNGLSHADERSOURCEPROC, glShaderSource) \
	decl(PFNGLCOMPILESHADERPROC, glCompileShader) \
	decl(PFNGLLINKPROGRAMPROC, glLinkProgram) \
	decl(PFNGLUSEPROGRAMPROC, glUseProgram) \
	decl(PFNGLDELETESHADERPROC, glDeleteShader) \
	decl(PFNGLGETSHADERIVPROC, glGetShaderiv) \
	decl(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) \
	decl(PFNGLUNIFORM1FVPROC, glUniform1fv) \
	decl(PFNGLUNIFORM2FVPROC, glUniform2fv) \
	decl(PFNGLUNIFORM3FVPROC, glUniform3fv) \
	decl(PFNGLUNIFORM4FVPROC, glUniform4fv) \
	decl(PFNGLUNIFORM1IVPROC, glUniform1iv) \
	decl(PFNGLUNIFORM2IVPROC, glUniform2iv) \
	decl(PFNGLUNIFORM3IVPROC, glUniform3iv) \
	decl(PFNGLUNIFORM4IVPROC, glUniform4iv) \
	decl(PFNGLUNIFORMMATRIX2FVPROC, glUniformMatrix2fv) \
	decl(PFNGLUNIFORMMATRIX3FVPROC, glUniformMatrix3fv) \
	decl(PFNGLUNIFORMMATRIX4FVPROC, glUniformMatrix4fv) \
	decl(PFNGLGENBUFFERSPROC, glGenBuffers) \
	decl(PFNGLBINDBUFFERPROC, glBindBuffer) \
	decl(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) \
	decl(PFNGLBUFFERDATAPROC, glBufferData) \
	decl(PFNGLBUFFERSUBDATAPROC, glBufferSubData) \
	decl(PFNGLMAPBUFFERPROC, glMapBuffer) \
	decl(PFNGLUNMAPBUFFERPROC, glUnmapBuffer) \
	decl(PFNGLISBUFFERPROC, glIsBuffer) \
	decl(PFNGLSTENCILFUNCSEPARATEPROC, glStencilFuncSeparate) \
	decl(PFNGLSTENCILOPSEPARATEPROC, glStencilOpSeparate) \
	decl(PFNGLGENQUERIESPROC, glGenQueries) \
	decl(PFNGLDELETEQUERIESPROC, glDeleteQueries) \
	decl(PFNGLISQUERYPROC, glIsQuery) \
	decl(PFNGLBEGINQUERYPROC, glBeginQuery) \
	decl(PFNGLENDQUERYPROC, glEndQuery) \
	decl(PFNGLGETQUERYIVPROC, glGetQueryiv) \
	decl(PFNGLGETQUERYOBJECTUIVPROC, glGetQueryObjectuiv) \
	decl(PFNWGLSWAPINTERVALEXTPROC, wglSwapIntervalEXT)
#elif _SB_LINUX_ || _SB_BSD_
#define QGGL_ENTRYPOINT_LIST(decl) \
	decl(PFNGLCLEARDEPTHFPROC, glClearDepthf) \
	decl(PFNGLDEPTHRANGEFPROC, glDepthRangef) \
	decl(PFNGLGENERATEMIPMAPPROC, glGenerateMipmap) \
	decl(PFNGLBLENDEQUATIONIPROC, glBlendEquationi) \
	decl(PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate) \
	decl(PFNGLBLENDEQUATIONSEPARATEIPROC, glBlendEquationSeparatei) \
	decl(PFNGLBLENDFUNCIPROC, glBlendFunci) \
	decl(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate) \
	decl(PFNGLBLENDFUNCSEPARATEIPROC, glBlendFuncSeparatei) \
	decl(PFNGLCOLORMASKIPROC, glColorMaski) \
	decl(PFNGLENABLEIPROC, glEnablei) \
	decl(PFNGLDISABLEIPROC, glDisablei) \
	decl(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) \
	decl(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) \
	decl(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) \
	decl(PFNGLVERTEXATTRIB4FVPROC, glVertexAttrib4fv) \
	decl(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) \
	decl(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) \
	decl(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers) \
	decl(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) \
	decl(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D) \
	decl(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers) \
	decl(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer) \
	decl(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) \
	decl(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) \
	decl(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer) \
	decl(PFNGLGETRENDERBUFFERPARAMETERIVPROC, glGetRenderbufferParameteriv) \
	decl(PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC, glGetFramebufferAttachmentParameteriv) \
	decl(PFNGLCREATEPROGRAMPROC, glCreateProgram) \
	decl(PFNGLDELETEPROGRAMPROC, glDeleteProgram) \
	decl(PFNGLATTACHSHADERPROC, glAttachShader) \
	decl(PFNGLDETACHSHADERPROC, glDetachShader) \
	decl(PFNGLGETATTACHEDSHADERSPROC, glGetAttachedShaders) \
	decl(PFNGLGETPROGRAMIVPROC, glGetProgramiv) \
	decl(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) \
	decl(PFNGLGETACTIVEATTRIBPROC, glGetActiveAttrib) \
	decl(PFNGLGETACTIVEUNIFORMPROC, glGetActiveUniform) \
	decl(PFNGLGETATTRIBLOCATIONPROC, glGetAttribLocation) \
	decl(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) \
	decl(PFNGLCREATESHADERPROC, glCreateShader) \
	decl(PFNGLSHADERSOURCEPROC, glShaderSource) \
	decl(PFNGLCOMPILESHADERPROC, glCompileShader) \
	decl(PFNGLLINKPROGRAMPROC, glLinkProgram) \
	decl(PFNGLUSEPROGRAMPROC, glUseProgram) \
	decl(PFNGLDELETESHADERPROC, glDeleteShader) \
	decl(PFNGLGETSHADERIVPROC, glGetShaderiv) \
	decl(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) \
	decl(PFNGLUNIFORM1FVPROC, glUniform1fv) \
	decl(PFNGLUNIFORM2FVPROC, glUniform2fv) \
	decl(PFNGLUNIFORM3FVPROC, glUniform3fv) \
	decl(PFNGLUNIFORM4FVPROC, glUniform4fv) \
	decl(PFNGLUNIFORM1IVPROC, glUniform1iv) \
	decl(PFNGLUNIFORM2IVPROC, glUniform2iv) \
	decl(PFNGLUNIFORM3IVPROC, glUniform3iv) \
	decl(PFNGLUNIFORM4IVPROC, glUniform4iv) \
	decl(PFNGLUNIFORMMATRIX2FVPROC, glUniformMatrix2fv) \
	decl(PFNGLUNIFORMMATRIX3FVPROC, glUniformMatrix3fv) \
	decl(PFNGLUNIFORMMATRIX4FVPROC, glUniformMatrix4fv) \
	decl(PFNGLGENBUFFERSPROC, glGenBuffers) \
	decl(PFNGLBINDBUFFERPROC, glBindBuffer) \
	decl(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) \
	decl(PFNGLBUFFERDATAPROC, glBufferData) \
	decl(PFNGLBUFFERSUBDATAPROC, glBufferSubData) \
	decl(PFNGLMAPBUFFERPROC, glMapBuffer) \
	decl(PFNGLUNMAPBUFFERPROC, glUnmapBuffer) \
	decl(PFNGLISBUFFERPROC, glIsBuffer) \
	decl(PFNGLSTENCILFUNCSEPARATEPROC, glStencilFuncSeparate) \
	decl(PFNGLSTENCILOPSEPARATEPROC, glStencilOpSeparate) \
	decl(PFNGLGENQUERIESPROC, glGenQueries) \
	decl(PFNGLDELETEQUERIESPROC, glDeleteQueries) \
	decl(PFNGLISQUERYPROC, glIsQuery) \
	decl(PFNGLBEGINQUERYPROC, glBeginQuery) \
	decl(PFNGLENDQUERYPROC, glEndQuery) \
	decl(PFNGLGETQUERYIVPROC, glGetQueryiv) \
	decl(PFNGLGETQUERYOBJECTUIVPROC, glGetQueryObjectuiv)
#else
#error fix me
#endif

#define QGGL_DECL_ENTRYPOINT(type,func) extern type func;
QGGL_ENTRYPOINT_LIST(QGGL_DECL_ENTRYPOINT);

// 
#include "qg_opengl.h"

//
struct qbOpenGLv4 : public qbOpenGLBase
{
	static void QglInitializeExtensions(const char* extstr);
	static bool QglTestExtensions();

	K_FORCEINLINE static GLint QglGetMaxOffScreenCount() { return qgl_max_off_screen_count; }

	// 기본
	K_FORCEINLINE static void QglClearDepth(GLdouble Depth)
	{
		glClearDepthf((GLfloat)Depth);
	}

	K_FORCEINLINE static void QglDepthRange(GLdouble Near, GLdouble Far)
	{
		glDepthRangef((GLfloat)Near, (GLfloat)Far);
	}

	// 텍스쳐
	K_FORCEINLINE static void QglActiveTexture(GLenum texture)
	{
		glActiveTexture(texture);
	}

	K_FORCEINLINE static void QglCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data)
	{
		glCompressedTexSubImage2D(target, level, 0, 0, width, height, internalformat, imageSize, data);
	}

	K_FORCEINLINE static void QglGenerateMipmap(GLenum target)
	{
		glGenerateMipmap(target);
	}

	// 블렌드
	K_FORCEINLINE static void QglBlendEquation(GLenum mode)
	{
		glBlendEquation(mode);
	}

	K_FORCEINLINE static void QglBlendEquationi(GLuint index, GLenum mode)
	{
		glBlendEquationi(index, mode);
	}

	K_FORCEINLINE static void QglBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
	{
		glBlendEquationSeparate(modeRGB, modeAlpha);
	}

	K_FORCEINLINE static void QglBlendEquationSeparatei(GLuint index, GLenum modeRGB, GLenum modeAlpha)
	{
		glBlendEquationSeparatei(index, modeRGB, modeAlpha);
	}

	K_FORCEINLINE static void QglBlendFunc(GLenum src, GLenum dst)
	{
		glBlendFunc(src, dst);
	}

	K_FORCEINLINE static void QglBlendFunci(GLuint index, GLenum src, GLenum dst)
	{
		glBlendFunci(index, src, dst);
	}

	K_FORCEINLINE static void QglBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)
	{
		glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
	}

	K_FORCEINLINE static void QglBlendFuncSeparatei(GLuint index, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)
	{
		glBlendFuncSeparatei(index, sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
	}

	K_FORCEINLINE static void QglColorMaski(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
	{
		glColorMaski(index, r, g, b, a);
	}

	K_FORCEINLINE static void QglEnableIndexed(GLenum target, GLuint index)
	{
		glEnablei(target, index);
	}

	K_FORCEINLINE static void QglDisableIndexed(GLenum target, GLuint index)
	{
		glDisablei(target, index);
	}

	// 레이아웃	
	K_FORCEINLINE static void QglEnableVertexArray(GLuint index)
	{
		glEnableVertexAttribArray(index);
	}

	K_FORCEINLINE static void QglDisableVertexArray(GLuint index)
	{
		glDisableVertexAttribArray(index);
	}

	K_FORCEINLINE static void QglVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer)
	{
		glVertexAttribPointer(index, size, type, normalized, stride, pointer);
	}

	// FBO
	K_FORCEINLINE static void QglGenFramebuffers(GLsizei n, GLuint* framebuffers)
	{
		glGenFramebuffers(n, framebuffers);
	}

	K_FORCEINLINE static void QglBindFramebuffer(GLenum target, GLuint framebuffer)
	{
		glBindFramebuffer(target, framebuffer);
	}

	K_FORCEINLINE static void QglDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
	{
		glDeleteFramebuffers(n, framebuffers);
	}

	K_FORCEINLINE static GLenum QglCheckFramebufferStatus(GLenum target)
	{
		return glCheckFramebufferStatus(target);
	}

	K_FORCEINLINE static void QglFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
	{
		glFramebufferTexture2D(target, attachment, textarget, texture, level);
	}

	K_FORCEINLINE static void QglGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
	{
		glGenRenderbuffers(n, renderbuffers);
	}

	K_FORCEINLINE static void QglBindRenderbuffer(GLenum target, GLuint renderbuffer)
	{
		glBindRenderbuffer(target, renderbuffer);
	}

	K_FORCEINLINE static void QglDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
	{
		glDeleteRenderbuffers(n, renderbuffers);
	}

	K_FORCEINLINE static void QglRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
	{
		glRenderbufferStorage(target, internalformat, width, height);
	}

	K_FORCEINLINE static void QglFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
	{
		glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
	}

	K_FORCEINLINE static void QglGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
	{
		glGetRenderbufferParameteriv(target, pname, params);
	}

	K_FORCEINLINE static void QglGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
	{
		glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
	}

	// 프로그램과 세이더
	K_FORCEINLINE static GLuint QglCreateProgram(void)
	{
		return glCreateProgram();
	}

	K_FORCEINLINE static void QglDeleteProgram(GLuint object)
	{
		glDeleteProgram(object);
	}

	K_FORCEINLINE static void QglAttachShader(GLuint program, GLuint shader)
	{
		glAttachShader(program, shader);
	}

	K_FORCEINLINE static void QglDetachShader(GLuint program, GLuint shader)
	{
		glDetachShader(program, shader);
	}

	K_FORCEINLINE static void QglGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
	{
		glGetAttachedShaders(program, maxcount, count, shaders);
	}

	K_FORCEINLINE static void QglGetProgramiv(GLuint program, GLenum type, GLint* param)
	{
		glGetProgramiv(program, type, param);
	}

	K_FORCEINLINE static void QglGetProgramInfoLog(GLuint program, GLsizei maxLength, GLsizei* length, GLchar* infoLog)
	{
		glGetProgramInfoLog(program, maxLength, length, infoLog);
	}

	K_FORCEINLINE static void QglGetActiveAttrib(GLuint program, GLuint index, GLsizei maxlength, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
	{
		glGetActiveAttrib(program, index, maxlength, length, size, type, name);
	}

	K_FORCEINLINE static void QglGetActiveUniform(GLuint program, GLuint index, GLsizei maxlength, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
	{
		glGetActiveUniform(program, index, maxlength, length, size, type, name);
	}

	K_FORCEINLINE static GLint QglGetAttribLocation(GLuint program, const GLchar *name)
	{
		return glGetAttribLocation(program, name);
	}

	K_FORCEINLINE static GLint QglGetUniformLocation(GLuint program, const GLchar* name)
	{
		return glGetUniformLocation(program, name);
	}

	K_FORCEINLINE static GLuint QglCreateShader(GLenum shaderType)
	{
		return glCreateShader(shaderType);
	}

	K_FORCEINLINE static void QglShaderSource(GLuint shader, GLsizei numOfStrings, const char** strings, const GLint* lengths)
	{
		glShaderSource(shader, numOfStrings, strings, lengths);
	}

	K_FORCEINLINE static void QglCompileShader(GLuint shader)
	{
		glCompileShader(shader);
	}

	K_FORCEINLINE static void QglLinkProgram(GLuint program)
	{
		glLinkProgram(program);
	}

	K_FORCEINLINE static void QglUseProgram(GLuint prog)
	{
		glUseProgram(prog);
	}

	K_FORCEINLINE static void QglDeleteShader(GLuint shader)
	{
		glDeleteShader(shader);
	}

	K_FORCEINLINE static void QglGetShaderiv(GLuint shader, GLenum type, GLint* param)
	{
		glGetShaderiv(shader, type, param);
	}

	K_FORCEINLINE static void QglGetShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei* length, GLchar* infoLog)
	{
		glGetShaderInfoLog(shader, maxLength, length, infoLog);
	}

	K_FORCEINLINE static void QglUniform1fv(GLint loc, GLsizei count, const GLfloat* v)
	{
		glUniform1fv(loc, count, v);
	}

	K_FORCEINLINE static void QglUniform2fv(GLint loc, GLsizei count, const GLfloat* v)
	{
		glUniform2fv(loc, count, v);
	}

	K_FORCEINLINE static void QglUniform3fv(GLint loc, GLsizei count, const GLfloat* v)
	{
		glUniform3fv(loc, count, v);
	}

	K_FORCEINLINE static void QglUniform4fv(GLint loc, GLsizei count, const GLfloat* v)
	{
		glUniform4fv(loc, count, v);
	}

	K_FORCEINLINE static void QglUniform1iv(GLint loc, GLsizei count, const GLint* v)
	{
		glUniform1iv(loc, count, v);
	}

	K_FORCEINLINE static void QglUniform2iv(GLint loc, GLsizei count, const GLint* v)
	{
		glUniform2iv(loc, count, v);
	}

	K_FORCEINLINE static void QglUniform3iv(GLint loc, GLsizei count, const GLint* v)
	{
		glUniform3iv(loc, count, v);
	}

	K_FORCEINLINE static void QglUniform4iv(GLint loc, GLsizei count, const GLint* v)
	{
		glUniform4iv(loc, count, v);
	}

	K_FORCEINLINE static void QglUniformMatrix2fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat* v)
	{
		glUniformMatrix2fv(loc, count, transpose, v);
	}

	K_FORCEINLINE static void QglUniformMatrix3fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat* v)
	{
		glUniformMatrix3fv(loc, count, transpose, v);
	}

	K_FORCEINLINE static void QglUniformMatrix4fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat* v)
	{
		glUniformMatrix4fv(loc, count, transpose, v);
	}

	// 버퍼
	K_FORCEINLINE static void QglGenBuffers(GLsizei n, GLuint* buffers)
	{
		glGenBuffers(n, buffers);
	}

	K_FORCEINLINE static void QglBindBuffer(GLenum target, GLuint buffer)
	{
		glBindBuffer(target, buffer);
	}

	K_FORCEINLINE static void QglDeleteBuffers(GLsizei n, const GLuint* buffers)
	{
		glDeleteBuffers(n, buffers);
	}

	K_FORCEINLINE static void QglBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
	{
		glBufferData(target, size, data, usage);
	}

	K_FORCEINLINE static void QglBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
	{
		glBufferSubData(target, offset, size, data);
	}

	K_FORCEINLINE static void* QglMapBuffer(GLenum target, GLenum access)
	{
		return glMapBuffer(target, access);
	}

	K_FORCEINLINE static GLboolean QglUnmapBuffer(GLenum target)
	{
		return glUnmapBuffer(target);
	}

	K_FORCEINLINE static GLboolean QglIsBuffer(GLuint buffer)
	{
		return glIsBuffer(buffer);
	}

	// 스텐실
	K_FORCEINLINE static void QglStencilFuncSeparate(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask)
	{
		glStencilFuncSeparate(frontfunc, backfunc, ref, mask);
	}

	K_FORCEINLINE static void QglStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
	{
		glStencilOpSeparate(face, fail, zfail, zpass);
	}

	// 오클루전
	K_FORCEINLINE static void QglGenQueries(GLsizei n, GLuint* ids)
	{
		glGenQueries(n, ids);
	}

	K_FORCEINLINE static void QglDeleteQueries(GLsizei n, const GLuint* ids)
	{
		glDeleteQueries(n, ids);
	}

	K_FORCEINLINE static GLboolean QglIsQuery(GLuint id)
	{
		return glIsQuery(id);
	}

	K_FORCEINLINE static void QglBeginQuery(GLenum target, GLuint id)
	{
		glBeginQuery(target, id);
	}

	K_FORCEINLINE static void QglEndQuery(GLenum target)
	{
		glEndQuery(target);
	}

	K_FORCEINLINE static void QglGetQueryiv(GLenum target, GLenum pname, GLint* params)
	{
		glGetQueryiv(target, pname, params);
	}

	K_FORCEINLINE static void QglGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
	{
		glGetQueryObjectuiv(id, pname, params);
	}

	// 기타
	K_FORCEINLINE static void QglSwapInterval(kpointer display, int interval)
	{
#if _QG_USE_SDL
#if SDL_VERSION_ATLEAST(1,3,0) 
		SDL_GL_SetSwapInterval(interval);
#else
		SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, interval);
#endif
#elif _SB_WINDOWS_
		wglSwapIntervalEXT(interval);
#else
#error need fix
#endif
	}


	K_FORCEINLINE static bool QglSwapBuffers(kpointer display, kpointer surface)
	{
#if _QG_USE_SDL
		SDL_GL_SwapBuffers();
		return true;
#elif _SB_WINDOWS_
		return SwapBuffers((HDC)display) != 0;
#else
#error need fix
#endif
	}

protected:
	static bool gl_shader_language_100;					// GL_ARB_shading_language_100
	static GLint qgl_max_off_screen_count;				// GL_ARB_DRAW_BUFFERS GL_MAX_DRAW_BUFFERS_ARB
};

//
typedef qbOpenGLv4 qbOpenGL;

#endif // !__INC_QG_OPENGL_V4_H__
